package smecta.client.print;

import javafx.application.Application;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import smecta.client.print.service.cache.biz.SerialPortConnectionCacheService;
import smecta.client.print.util.AlertUtil;
import smecta.client.print.util.AuthUtil;

import java.net.URL;

@Slf4j
@SpringBootApplication
public class SpringbootJavafxApplication extends Application {
    // 任何地方都可以通过这个applicationContext获取springboot的上下文
    public static ConfigurableApplicationContext applicationContext;

    public static HostServices hostServices;
    private static String[] args;

    private Stage splashStage = null;
    private static Throwable error;

    public static void main(String[] args) {
        SpringbootJavafxApplication.args = args;
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        hostServices = getHostServices();
        if (error != null) {
            String errorCode = String.format("SCP-APP-START-%s", System.currentTimeMillis());
            log.error("SpringbootJavafxApplication start exception, code:{}, stack:{}", errorCode, error);
            AlertUtil.error(String.format("程序启动出错\n 错误代码:%s \n 错误信息:%s \n\n 可联系技术人员进行支持, 联系电话: 8257001", errorCode, error.getMessage()));
            return;
        }
        closeSplashScreen();
        if(checkLicense()){
            showLoginPage(primaryStage);
        }else{
            showAuthPage(primaryStage);
        }

    }

    @Override
    public void init() {
        try {
            // 使用 runLater 确保在 JavaFX 应用程序线程上执行
            Platform.runLater(() -> showSplashScreen());
            // 启动springboot
            applicationContext = SpringApplication.run(SpringbootJavafxApplication.class, args);
        } catch (Throwable e) {
            closeSplashScreen();
            error = e;
        }
    }

    @Override
    public void stop() throws Exception {
        SerialPortConnectionCacheService.closeAll();
        // 关闭springboot
        applicationContext.stop();
    }

    private void showSplashScreen() {
        try {
            FXMLLoader splashLoader = new FXMLLoader(getClass().getResource("/fxml/SplashView.fxml"));
            VBox splashRoot = splashLoader.load();
            splashStage = new Stage();
            splashStage.setScene(new Scene(splashRoot));
            splashStage.setTitle("亿维通");
            splashStage.show();
        } catch (Exception e) {
            log.error("showSplashScreen error stack:{}", e);
        }
    }

    private void closeSplashScreen() {
        Platform.runLater(() -> {
            try {
                if (splashStage != null) {
                    splashStage.close();
                }
            } catch (Exception e) {
                log.error("Error closing splash screen", e);
            }
        });
    }

    private void showAuthPage(Stage primaryStage) throws Exception {
        URL resource = getClass().getResource("/fxml/LicenseView.fxml");
        if (resource == null) {
            throw new Exception();
        }
        // 加载 fxml 下面的逻辑可以单独封装
        FXMLLoader loader = new FXMLLoader(resource);
        loader.setControllerFactory(new Callback<Class<?>, Object>() {
            @Override
            public Object call(Class<?> param) {
                // 控制器工厂提供bean注入，此处的缺点是不能根据bean名字注入，只能通过class类型注入bean
                // 解决方案：
                // 1、SpringbootJavafxApplication.applicationContext.getBean("Bean Name", Bean.class);
                // 2、@Autowired private ApplicationContext applicationContext;
                // Object bean_name = applicationContext.getBean("bean Name", Bean.class);
                return applicationContext.getBean(param);
            }
        });
        // 加载
        VBox root = loader.load();
        primaryStage.setScene(new Scene(root));
        primaryStage.setTitle("激活界面");
        primaryStage.show();
    }

    private void showLoginPage(Stage primaryStage) throws Exception {
        URL resource = getClass().getResource("/fxml/LoginView.fxml");
        if (resource == null) {
            throw new Exception();
        }
        // 加载 fxml 下面的逻辑可以单独封装
        FXMLLoader loader = new FXMLLoader(resource);
        loader.setControllerFactory(new Callback<Class<?>, Object>() {
            @Override
            public Object call(Class<?> param) {
                // 控制器工厂提供bean注入，此处的缺点是不能根据bean名字注入，只能通过class类型注入bean
                // 解决方案：
                // 1、SpringbootJavafxApplication.applicationContext.getBean("Bean Name", Bean.class);
                // 2、@Autowired private ApplicationContext applicationContext;
                // Object bean_name = applicationContext.getBean("bean Name", Bean.class);
                return applicationContext.getBean(param);
            }
        });
        // 加载
        VBox root = loader.load();
        primaryStage.setScene(new Scene(root));
        primaryStage.setTitle("登录界面");
        primaryStage.show();
    }

    public boolean checkLicense(){
        AuthUtil.loadPrintSettings();
        return AuthUtil.check();
    }
}
